// Copyright 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)
//
// This is a public header file, it must only include public header files.

#ifndef MUDUO_NET_TCPCONNECTION_H
#define MUDUO_NET_TCPCONNECTION_H

#include "muduo/base/noncopyable.h"
#include "muduo/base/StringPiece.h"
#include "muduo/base/Types.h"
#include "muduo/net/Callbacks.h"
#include "muduo/net/Buffer.h"
#include "muduo/net/InetAddress.h"

#include <memory>

#include <boost/any.hpp>

// struct tcp_info is in <netinet/tcp.h>
struct tcp_info;

namespace muduo
{
namespace net
{

class Channel;
class EventLoop;
class Socket;

///
/// TCP connection, for both client and server usage.
///
/// This is an interface class, so don't expose too much details.
class TcpConnection : noncopyable,
                      public std::enable_shared_from_this<TcpConnection>
{
 public:
  /// Constructs a TcpConnection with a connected sockfd
  ///
  /// User should not create this object.
  TcpConnection(EventLoop* loop,
                const string& name,
                int sockfd,
                const InetAddress& localAddr,
                const InetAddress& peerAddr);
  ~TcpConnection();
  //获取Event Loop
  EventLoop* getLoop() const { return loop_; }
  //获取链接的名字
  const string& name() const { return name_; }
  const InetAddress& localAddress() const { return localAddr_; }
  const InetAddress& peerAddress() const { return peerAddr_; }
  //判断链接是否建立成功
  bool connected() const { return state_ == kConnected; }
  //判断链接是否断开成功
  bool disconnected() const { return state_ == kDisconnected; }
  // return true if success.
  bool getTcpInfo(struct tcp_info*) const;
  string getTcpInfoString() const;

  // void send(string&& message); // C++11
  void send(const void* message, int len);
  void send(const StringPiece& message);
  // void send(Buffer&& message); // C++11
  void send(Buffer* message);  // this one will swap data
  void shutdown(); // NOT thread safe, no simultaneous calling
  // void shutdownAndForceCloseAfter(double seconds); // NOT thread safe, no simultaneous calling
  //关闭链接，用loop的queueInLoop把forceCloseInLoop抛入到具有线程安全的任务队列中，forceCloseInLoop又会去调用链接关闭回调
  void forceClose();
  //等待seconds秒关闭链接，如果不是Event Loop绑定的IO线程，这个方法也会被抛入到任务队列中
  void forceCloseWithDelay(double seconds);
  //是否降低延时，设置TCP_NODELAY，即使小数据包也会被立即发送出去
  void setTcpNoDelay(bool on);
  // reading or not
  //启动读事件监控，会调用runInLoop来保证线程安全
  void startRead();
  //停止读事件监控
  void stopRead();
  //是否在进行读事件监控
  bool isReading() const { return reading_; }; // NOT thread safe, may race with start/stopReadInLoop
  //设置链接上下文
  void setContext(const boost::any& context)
  { context_ = context; }
  //获取链接上下文
  const boost::any& getContext() const
  { return context_; }
  //获取链接上下文
  boost::any* getMutableContext()
  { return &context_; }
  //设置链接的链接建立回调
  void setConnectionCallback(const ConnectionCallback& cb)
  { connectionCallback_ = cb; }
  //设置链接的消息到来的回调
  void setMessageCallback(const MessageCallback& cb)
  { messageCallback_ = cb; }
  //设置低水位回调，如果发送缓冲区被清空就去调用它，低水位回调会在send()和handleWrite()的时候会触发（读事件回调）
  void setWriteCompleteCallback(const WriteCompleteCallback& cb)
  { writeCompleteCallback_ = cb; }
  //设置高水位回调，和高水位线，高水位回调在send()发送数据的时候会触发
  void setHighWaterMarkCallback(const HighWaterMarkCallback& cb, size_t highWaterMark)
  { highWaterMarkCallback_ = cb; highWaterMark_ = highWaterMark; }

  /// Advanced interface
  //获取读缓冲区
  Buffer* inputBuffer()
  { return &inputBuffer_; }
  //获取写缓冲区
  Buffer* outputBuffer()
  { return &outputBuffer_; }

  /// Internal use only.
  //设置链接关闭回调
  void setCloseCallback(const CloseCallback& cb)
  { closeCallback_ = cb; }

  // called when TcpServer accepts a new connection
  void connectEstablished();   // should be called only once
  // called when TcpServer has removed me from its map
  void connectDestroyed();  // should be called only once

 private:
  enum StateE { kDisconnected,  //断开连接状态
                kConnecting,    //尝试建立连接的状态
                kConnected,     //成功建立连接的状态
                kDisconnecting  //正在断开连接的状态
                };
  //链接的各种回调
  void handleRead(Timestamp receiveTime);
  void handleWrite();//不管是handleWrite还是send(),都只调用一次write()系统调用，如果数据没有发送完也直接返回，等待下一次写事件通知，如果数据发送完了，则关闭写事件监控
  void handleClose();
  void handleError();
  // void sendInLoop(string&& message);
  //sendInLoop把发送数据的动作放到到具有线程安全的任务队列中
  void sendInLoop(const StringPiece& message);
  void sendInLoop(const void* message, size_t len);
  //关闭通信文件描述符的写操作
  void shutdownInLoop();
  // void shutdownAndForceCloseInLoop(double seconds);
  //这个函数会调用链接的关闭回调handleClose()
  void forceCloseInLoop();
  //设置状态
  void setState(StateE s) { state_ = s; }
  //获取链接的状态
  const char* stateToString() const;
  //启动链接的读事件监控
  void startReadInLoop();
  //停止链接的读事件监控
  void stopReadInLoop();

  EventLoop* loop_; //把一个链接挂接到EventLoop上进行事件监控
  const string name_; //链接的名字
  StateE state_;  //链接的状态  // FIXME: use atomic variable
  bool reading_;  //为true表示链接正在进行读事件监控
  // we don't expose those classes to client.
  std::unique_ptr<Socket> socket_;
  std::unique_ptr<Channel> channel_;
  const InetAddress localAddr_;                     //IP地址的简单封装
  const InetAddress peerAddr_;
  ConnectionCallback connectionCallback_;           //新建链接的回调
  MessageCallback messageCallback_;                 //消息到来的回调
  WriteCompleteCallback writeCompleteCallback_;     //低水位线回调
  HighWaterMarkCallback highWaterMarkCallback_;     //高水位线回调
  CloseCallback closeCallback_;
  size_t highWaterMark_;
  Buffer inputBuffer_;  //客户代码从 inputBuffer_ 读，
  Buffer outputBuffer_; //客户代码往 outputBuffer_ 写 // FIXME: use list<Buffer> as output buffer.
  boost::any context_;  //链接的上下文
  // FIXME: creationTime_, lastReceiveTime_
  //        bytesReceived_, bytesSent_
};

typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;  //用智能指针管理链接

}  // namespace net
}  // namespace muduo

#endif  // MUDUO_NET_TCPCONNECTION_H
